package scatter.order.rest.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.Assert;
import scatter.common.rest.exception.BusinessDataNotFoundException;
import scatter.common.rest.service.IBaseQueryFormService;
import scatter.order.pojo.form.OrderPageQueryForm;
import scatter.order.pojo.po.Order;
import scatter.order.pojo.po.OrderGoods;
import scatter.order.pojo.vo.OrderGoodsVo;
import scatter.order.pojo.vo.OrderVo;
import scatter.order.pojo.vo.QueryOrderVo;
import scatter.order.rest.mapstruct.OrderGoodsMapStruct;
import scatter.order.rest.mapstruct.OrderMapStruct;
import scatter.order.rest.service.IOrderGoodsService;
import scatter.order.rest.service.IOrderService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * <p>
 * 默认订单查询服务实现
 * </p>
 *
 * @author yangwei
 * @since 2021-07-05 00:51
 */
@Slf4j
public class DefaultQueryOrderFrameworkServiceImpl extends AbstractQueryOrderFrameworkServiceImpl<OrderPageQueryForm, QueryOrderVo> {

	@Autowired
	private IOrderService iOrderService;
	@Autowired
	private IOrderGoodsService iOrderGoodsService;

	@Autowired
	private IBaseQueryFormService<Order,OrderPageQueryForm> orderPageQueryFormIBaseQueryFormService;

	@Qualifier("commonDbTaskExecutor")
	@Autowired
	protected ExecutorService executorService;

	@Override
	protected QueryOrderVo doGetOrderByOrderNo(String orderNo) {
		Assert.hasText(orderNo, "orderNo 不能为空");

		Order byOrderNo = iOrderService.getByOrderNo(orderNo);
		if (byOrderNo == null) {
			throw new BusinessDataNotFoundException("不存在的订单号 " + orderNo);
		}


		List<Future<List<ExtFutureDto>>> futures = extFutures(newArrayList(byOrderNo.getId()));


		// 查询商品信息
		List<OrderGoods> byOrderId = iOrderGoodsService.getByOrderId(byOrderNo.getId());

		// 转vo
		OrderVo orderVo = OrderMapStruct.INSTANCE.poToVo(byOrderNo);
		List<OrderGoodsVo> orderGoodsVos = OrderGoodsMapStruct.INSTANCE.posToVos(byOrderId);

		Map<String,List<ExtFutureDto>> extMap = getExtFutureDtoMap(futures);


		// 返回结果
		QueryOrderVo queryOrderVo = new QueryOrderVo();
		queryOrderVo.setOrder(orderVo);
		queryOrderVo.setOrderGoods(orderGoodsVos);
		setExt(queryOrderVo,extMap);
		return queryOrderVo;
	}

	@Override
	protected Page<QueryOrderVo> doQueryOrderPage(OrderPageQueryForm param) {

		Page orderPage = orderPageQueryFormIBaseQueryFormService.listPage(param);
		int recordSize = orderPage.getRecords().size();
		if (recordSize == 0) {
			throw new BusinessDataNotFoundException("数据不存在");
		}


		List<QueryOrderVo> r = new ArrayList<>(recordSize);
		QueryOrderVo queryOrderVo = null;
		Order order = null;

		List<String> orderIds = new ArrayList<>(recordSize);
		// 将查询到的实体转为vo
		for (Object record : orderPage.getRecords()) {
			order = ((Order) record);
			orderIds.add(order.getId());
			queryOrderVo = new QueryOrderVo();
			queryOrderVo.setOrder(OrderMapStruct.INSTANCE.poToVo(((Order) record)));
			r.add(queryOrderVo);
		}

		// 重置vo
		orderPage.setRecords(r);

		Future<List<OrderGoodsVo>> orderGoodsFuture = executorService.submit(()-> OrderGoodsMapStruct.INSTANCE.posToVos(iOrderGoodsService.getByOrderIds(orderIds)));

		List<Future<List<ExtFutureDto>>> futures = extFutures(orderIds);

		Map<String,List<ExtFutureDto>> extMap = getExtFutureDtoMap(futures);

		List<OrderGoodsVo> goodsList = null;
		try {
			goodsList = orderGoodsFuture.get();
		} catch (InterruptedException e) {
			log.error("订单分页查询框架默认实现，线程池异步获取商品中断异常",e);
		} catch (ExecutionException e) {
			log.error("订单分页查询框架默认实现，线程池异步获取商品异常",e);
		}



		Map<String, List<OrderGoodsVo>>  OrderGoodsVoMap = null;
		if (goodsList != null) {
			OrderGoodsVoMap = goodsList.stream().collect(Collectors.groupingBy(OrderGoodsVo::getOrderId));
		}

		// 异步获取商品信息
		for (Object record : orderPage.getRecords()) {
			queryOrderVo = ((QueryOrderVo) record);
			if (OrderGoodsVoMap != null) {
				queryOrderVo.setOrderGoods(OrderGoodsVoMap.get(queryOrderVo.getOrder().getId()));
			}
			// 设置额外信息
			setExt(queryOrderVo,extMap);
		}



		return orderPage;
	}

	/**
	 * 获取异步获取的结果
	 * @param futures
	 * @return
	 */
	private Map<String,List<ExtFutureDto>> getExtFutureDtoMap(List<Future<List<ExtFutureDto>>> futures){
		List<ExtFutureDto> extFutureDtoList = new ArrayList<>();
		if (futures != null) {
			for (Future<List<ExtFutureDto>> future : futures) {
				try {
					List<ExtFutureDto> extFutureDtos = future.get();
					if (extFutureDtos != null) {
						extFutureDtoList.addAll(extFutureDtos);
					}
				} catch (InterruptedException e) {
					log.error("订单分页查询框架默认实现，线程池异步获取额外信息中断异常",e);
				} catch (ExecutionException e) {
					log.error("订单分页查询框架默认实现，线程池异步获取额外信息异常",e);
				}

			}
		}
		Map<String,List<ExtFutureDto>> extMap = null;
		if (!extFutureDtoList.isEmpty()) {
			extMap = extFutureDtoList.stream().collect(Collectors.groupingBy(ExtFutureDto::getOrderId));
		}
		return extMap;
	}

	/**
	 * 设置额外信息
	 * @param queryOrderVo
	 * @param extMap
	 */
	private void setExt(QueryOrderVo queryOrderVo,Map<String,List<ExtFutureDto>> extMap){
		if (extMap != null) {
			Map<String,Object> ext = queryOrderVo.getExt();
			if (ext == null) {
				ext = new HashMap<>();
			}
			for (ExtFutureDto extFutureDto : extMap.get(queryOrderVo.getOrder().getId())) {
				ext.putAll(extFutureDto.getExt());

			}
			queryOrderVo.setExt(ext);
		}
	}

	/**
	 * 额外信息处理
	 * @param orderIds
	 * @return
	 */
	protected List<Future<List<ExtFutureDto>>> extFutures(List<String> orderIds){
		return null;
	}

	/**
	 * 额外扩展信息
	 */
	@Setter
	@Getter
	@NoArgsConstructor
	@AllArgsConstructor
	protected class ExtFutureDto{
		private String orderId;
		private Map<String, Object> ext;
	}

}
